home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc / Sample Code / CALib & You… / Source / CASample / CAS_Drag.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-07  |  37.3 KB  |  1,522 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        CAS_Drag.c
  3.  
  4.     Contains:    All the code to handle dragging for the CASample app. 
  5.  
  6.     Written by:    David H Nelson (from DragText by Rob Johnston)
  7.  
  8.     Copyright © 1993-1995 ComponentWorks, All rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <15>      5/19/93    SJF        Kill the check for drop location is finder trash
  13.                                      because the AECoerceDesc call crashes
  14.          <1>     11/20/93    DHN        Created from Scrapbook.c.
  15.  
  16. */
  17.  
  18. #include <Folders.h>
  19.  
  20. #ifdef USE_CALIB
  21. #include "CALib.h"
  22. #include "CAS_CAUtil.h"
  23. #endif
  24.  
  25. #include "CAS_Globals.h"
  26. #include "CAS_Drag.h"
  27. #include "CAS_Misc.h"
  28. #include "CAS_Doc.h"
  29. #include "CAS_App.h"
  30. #include "CAS_StringTools.h"
  31. #include "CAS_Content.h"
  32.  
  33. #include <String.h>
  34.  
  35. //----------------------------------------------------------------------
  36. //     local prototypes
  37.  
  38. #if defined(__cplusplus)
  39. extern "C"
  40. {
  41. #endif
  42.  
  43. static short HitTest(Point theLoc, DocPtr theDoc);
  44. static OSErr GetResFromFile(FSSpec *fileSpec, Handle *h, OSType theType);
  45. static OSErr GetDataFromFile(FSSpec *fileSpec, Handle *h, long offset, long maxLength);
  46. static Boolean IsMyTypeAvailable(DragReference theDrag);
  47. static Boolean DropLocationIsFinderTrash(
  48.     AEDesc    *dropLocation );
  49. static OSErr GetDropFSSpec(DragReference theDrag, FSSpec *dropFSSpec);
  50.  
  51. #if defined(__cplusplus)
  52. }
  53. #endif
  54.  
  55. #define PROMISES 1
  56.  
  57.  
  58. //static short        insertionOffset, insertionShow, lastOffset, insertPosition;
  59. static Boolean        canAcceptItems;
  60. static short        cursorInContent;
  61.  
  62. static Boolean        localDragInProgress = false;
  63.  
  64.  
  65. //===========================================================================
  66. #pragma mark '    CASample Drag Callbacks
  67. //===========================================================================
  68.  
  69.  
  70. #ifdef USE_CALIB
  71.  
  72. pascal OSErr Drag_DragReceiveHandler(
  73.     WindowPtr        theWindow,
  74.     void            *handlerRefCon,
  75.     DragReference    theDrag )
  76. {
  77. OSErr                theErr;
  78. OSErr                returnErr = dragNotAcceptedErr;
  79. unsigned short        numItems, index;
  80. DragAttributes        attributes;
  81. short                mouseDownModifiers, mouseUpModifiers;
  82. GrafPtr                savePort;
  83. Point                saveOrigin;
  84. DocPtr                theDoc;
  85. Boolean                skipPict = false;
  86. Point                dropMouse, pinnedMouse;
  87. FSSpec                fileSpec;
  88.  
  89.     // if we can't accept the item flavors or the cursor isn't over the item frame,
  90.     // don't accept the drag.
  91.     if (!canAcceptItems || !cursorInContent)
  92.         return dragNotAcceptedErr;
  93.  
  94.     theDoc = (DocPtr)GetWRefCon( theWindow );
  95.  
  96.     GetPort( &savePort );
  97.     SetPort( (GrafPtr)theWindow );
  98.  
  99.     theErr = GetDragAttributes( theDrag, &attributes );
  100.  
  101.     // are we moving the items within our own window?
  102.     if ((attributes & dragInsideSenderWindow) &&
  103.         (localDragInProgress))
  104.     {
  105.         Point    startPt, endPt;
  106.  
  107.         // This is where we move the items.
  108.         theErr = GetDragOrigin( theDrag, &startPt );
  109.         theErr = GetDragMouse( theDrag, &endPt, nil );
  110.  
  111.         Doc_MoveSelection( theDoc, endPt.h - startPt.h, endPt.v - startPt.v );
  112.  
  113.         SetPort( savePort );
  114.         return noErr;
  115.     }
  116.  
  117.     theErr = GetDragModifiers( theDrag, 0L, &mouseDownModifiers, &mouseUpModifiers );
  118.     if (theErr != noErr)
  119.     {
  120.         SetPort( savePort );
  121.         return theErr;
  122.     }
  123.  
  124.     theErr = CountDragItems( theDrag, &numItems );
  125.     if (theErr != noErr)
  126.     {
  127.         SetPort( savePort );
  128.         return theErr;
  129.     }
  130.  
  131.     if (numItems <= 0)            // if there is nothing to receive…
  132.     {
  133.         SetPort( savePort );
  134.         theErr = dragNotAcceptedErr;
  135.         return theErr;
  136.     }
  137.  
  138.     // turn off the hiliting if needed
  139.     if (attributes & dragHasLeftSenderWindow)
  140.         HideDragHilite( theDrag );
  141.  
  142. //    page = GetCtlValue(theDoc->scrollBar);                            /* get current page */
  143.  
  144.     //    Loop through all of the drag items contained in this drag and add an item for each.
  145.     for (index = 1; index <= numItems; index++)
  146.     {
  147.         ItemReference        theItem;
  148.         unsigned short        numFlavors;
  149.         unsigned short        flavorIndex;
  150.         FlavorType            theType;
  151.         Size                dataSize;
  152.         FlavorFlags            theFlags;
  153.         Handle                dataHandle = NULL;
  154.         Rect                itemBounds;
  155.         Rect                docBounds;
  156.         GrafPtr                savePort;
  157.         CADocumentRef        dragDropDoc, insertDoc;
  158.         CACloneKind            cloneKind;
  159.  
  160.  
  161.         //    Get the item's reference number, so we can refer to it.
  162.         // count the number of item flavors.
  163.         theErr = GetDragItemReferenceNumber( theDrag, index, &theItem );
  164.         theErr = CountDragItemFlavors( theDrag, theItem, &numFlavors );
  165.             
  166.         // First Check for our internal type
  167.         if (Drag_DragItemHasFlavor (theDrag, theItem, kCACASScrapType))
  168.         {
  169.             theType = kCACASScrapType;
  170.             dataHandle = Drag_GetFlavorData (theDrag, theItem, kCACASScrapType);
  171.             if (dataHandle == NULL) return dragNotAcceptedErr;
  172.         }
  173.         
  174.         // Now check for flavorTypeHFS 
  175.         else if (Drag_DragItemHasFlavor (theDrag, theItem, flavorTypeHFS))
  176.         {
  177.         
  178.             HFSFlavor        theHFSFlavor;
  179.  
  180.             dataHandle = Drag_GetFlavorData (theDrag, theItem, flavorTypeHFS);
  181.             if (dataHandle == NULL) return dragNotAcceptedErr;
  182.  
  183.             // save the flavor
  184.             BlockMoveData( *dataHandle, &theHFSFlavor, (long)sizeof(HFSFlavor) );
  185.  
  186.             if (theHFSFlavor.fileType == kPICTType)                // PICT file?
  187.             {
  188.             
  189.                 theType = kPICTType;
  190.                 DisposeHandle( dataHandle );    // throw away the handle, we'll get a new one.
  191.                 dataHandle = nil;
  192.             
  193.                 // open the data fork and read the pict out of it.
  194.                 theErr = GetDataFromFile(&theHFSFlavor.fileSpec, &dataHandle, 512, 0x7FFFFFFF);
  195.                 
  196.             }
  197.             else if (theHFSFlavor.fileCreator == 'drag')    // CREATOR is Finder clipping file?
  198.             {
  199.                 // ignore it since we'll get the clipping flavors also.
  200.                 theErr = noErr;
  201.             }
  202.             else if (theHFSFlavor.fileCreator == kODShellSignature)
  203.             {
  204.                 theType = kODShellSignature;        
  205.                 insertDoc = CAOpenDocument (&theHFSFlavor.fileSpec, NULL, 0, 0);
  206.                 theErr = CAError();
  207.                 
  208.             }
  209.             else if (theHFSFlavor.fileCreator == kOurFileCreator)
  210.             {
  211.                 theType = kOurFileCreator;
  212.                 BlockMove (&theHFSFlavor.fileSpec, &fileSpec, sizeof (FSSpec));
  213.             }
  214.             else
  215.                 // indicate we don't have anything.
  216.                 theErr = resNotFound;
  217.  
  218.         }
  219.         
  220.         // If kCAPromiseFlavor is present their is a part in the drag.
  221.         else if (Drag_DragItemHasFlavor (theDrag, theItem, kCAPromiseFlavor))
  222.         {
  223.             theType = kCAPromiseFlavor;            
  224.         }
  225.  
  226.         // Last resort kPICTType
  227.         else if (Drag_DragItemHasFlavor (theDrag, theItem, kPICTType))
  228.         {
  229.             theType = kPICTType;
  230.             dataHandle = Drag_GetFlavorData (theDrag, theItem, kPICTType);
  231.             if (dataHandle == NULL) return dragNotAcceptedErr;
  232.  
  233.         }
  234.         
  235.         // Set the port
  236.         
  237.         GetPort( &savePort );
  238.         SetPort( (GrafPtr)Doc_GetWindow( theDoc ) );
  239.  
  240.         // Compute the drop location
  241.  
  242.         // Get the drag region
  243.         GetDragItemBounds( theDrag, theItem, &itemBounds );
  244.  
  245.         // Convert it from global to theDoc local coordinates
  246.  
  247.         OffsetRect(    &itemBounds,
  248.                     GetControlValue( theDoc->hScrollBar ),
  249.                     GetControlValue( theDoc->vScrollBar ) );
  250.  
  251.         dropMouse.v = itemBounds.top;
  252.         dropMouse.h = itemBounds.left;
  253.     
  254.         GlobalToLocal (&dropMouse);
  255.  
  256.         switch (theType)
  257.         {
  258.         
  259.             case kODShellSignature:
  260.  
  261.                     
  262.                 CAUtil_EmbedODContainerFromCADocument (theDoc, insertDoc, dropMouse);
  263.                 CACloseDocument (insertDoc);
  264.                 returnErr = noErr;
  265.                 break;
  266.                 
  267.             case kCACASScrapType:
  268.  
  269.                 // Note: This case is not covered since a kCACASScrapType drag
  270.                 // is a kCAPromiseFlavor flavor with a part kind of kCACASScrapType
  271.                 
  272.                 // Get the ODDragDrop object
  273.                     
  274.                 dragDropDoc = CAGetDragDropDocument(theItem);
  275.                 Doc_AddItemsFromCAScrap( theDoc, dataHandle, &dropMouse, dragDropDoc,
  276.                                             kCACloneDropCopy );
  277.  
  278.                 CACloseDocument (dragDropDoc);
  279.                 returnErr = noErr;
  280.                 break;
  281.                 
  282.             case flavorTypeHFS:
  283.             
  284.                 returnErr = dragNotAcceptedErr;
  285.                 break;
  286.                 
  287.             case kPICTType:
  288.                 Doc_AddItemPict( theDoc, (PicHandle)dataHandle, dropMouse );
  289.                 returnErr = noErr;
  290.                 break;
  291.                 
  292.             case kCAPromiseFlavor:
  293.             {
  294.  
  295.                 CAISOStr    partKind;
  296.                 dragDropDoc = CAGetDragDropDocument(theItem);
  297.                 
  298.                 partKind = CAGetDocumentKind (dragDropDoc);
  299.                 
  300.                 if (bCStrCmp (partKind, kCACASScrapTypeStr))
  301.                 {
  302.                 
  303.                     Handle        scrapHandle;
  304.                     CASize        scrapLength;
  305.                     
  306.                     CASetOffset (dragDropDoc, 0);
  307.                     scrapLength = CAGetSize (dragDropDoc);
  308.                     
  309.                     scrapHandle = NewHandle (scrapLength);
  310.                     CARead (dragDropDoc, *scrapHandle, &scrapLength);
  311.                     
  312.                     Doc_AddItemsFromCAScrap( theDoc, scrapHandle, &dropMouse, dragDropDoc,
  313.                                             kCACloneDropCopy );
  314.         
  315.                     Win_ShowSelection( Doc_GetWindow( theDoc ) );
  316.                     DisposeHandle( scrapHandle );
  317.         
  318.         
  319.                 }
  320.                 else
  321.                 {
  322.                     CAUtil_EmbedODContainerFromCADocument (theDoc, dragDropDoc, dropMouse);
  323.                 }
  324.                 
  325.                 DisposePtr (partKind);
  326.                 CACloseDocument (dragDropDoc);
  327.                 returnErr = noErr;
  328.  
  329.                 break;
  330.             }
  331.             case kOurFileCreator:
  332.             {
  333.                 // Deselect everything
  334.                 Doc_SelectAllElements( theDoc, false );
  335.  
  336.                 // incorporate the CASample file contents in theDoc
  337.                 returnErr = CAUtil_AddItemsFromDocFile (theDoc, &fileSpec, &dropMouse);
  338.             }
  339.                 
  340.         }
  341.         
  342.         SetPort( savePort );
  343.  
  344.         if (dataHandle)
  345.         {
  346.             DisposeHandle(dataHandle);
  347.             dataHandle = NULL;
  348.         }
  349.         
  350.     }
  351.  
  352. #endif
  353.         
  354.     
  355.     if (returnErr == noErr)
  356.     {
  357.         CARequestStandardFocusSet (theWindow);
  358.         App_SetFrontDocWindow (theWindow);
  359.         Doc_SetDirty(theDoc, true);         // mark it changed
  360.     }
  361.     
  362.     return returnErr;
  363. }
  364.  
  365. //---------------------------------------------------------------------------
  366. //
  367. //    Drag_DragTrackingHandler - This is the drag tracking handler for windows in the 
  368. //    Scrapbook application.
  369.  
  370. pascal OSErr Drag_DragTrackingHandler(
  371.     short            message,
  372.     WindowPtr        theWindow,
  373.     void            *handlerRefCon,
  374.     DragReference    theDrag )
  375. {
  376. short            offset;
  377. unsigned long    attributes;
  378. RgnHandle        theRgn;
  379. DocPtr            theDoc;
  380. Point            theMouse, localMouse;
  381.  
  382.     if ((message != dragTrackingEnterHandler) && !canAcceptItems)
  383.         return noErr;
  384.  
  385.     // get the window theDoc.
  386.     theDoc = (DocPtr)GetWRefCon( theWindow );
  387.     GetDragAttributes( theDrag, &attributes );
  388.  
  389.     switch (message)
  390.     {
  391.         case dragTrackingEnterHandler:
  392.  
  393.             //    We get called with this message the first time that a drag enters ANY
  394.             //    window in our application. Check to see if all of the drag items contain
  395.             //    a flavor we accept (which is any flavor), otherwise set canAcceptItems false.
  396.             canAcceptItems = !theDoc->fileLocked && IsMyTypeAvailable(theDrag);    // was true
  397.             break;
  398.  
  399.         case dragTrackingEnterWindow:
  400.             //    We receive an EnterWindow message each time a drag enters one of our
  401.             //    application's windows. We initialize our global variables for tracking
  402.             //    the drag through the window.
  403.             cursorInContent = false;
  404.             break;
  405.  
  406.         case dragTrackingInWindow:
  407.             //    We receive InWindow messages as long as the mouse is in one of our windows
  408.             //    during a drag. We draw the window highlighting and blink the insertion caret
  409.             //    when we get these messages.
  410.             
  411.             GetDragMouse( theDrag, &theMouse, 0L );
  412.             localMouse = theMouse;
  413.             GlobalToLocal( &localMouse );
  414.  
  415.             //    Show or hide the window highlighting when the mouse enters or leaves the
  416.             //    item frame in our window (we don't want to show the highlighting when
  417.             //    the mouse is over the window title bar or anywhere else).
  418.  
  419. //            if (attributes & dragHasLeftSenderWindow)
  420. //            {
  421.                 // We assume that the drag manager sets our port before calling us
  422.                 // so we can set the background color to white. If we don't, the
  423.                 // ShowDragHilite and HideDragHilite don't seem to do anything.
  424. // $$$$$                RGBBackColor(&theDoc->whiteColor);
  425.             if (PtInRect( localMouse, &theDoc->contentRect ))
  426.             {
  427.                 if (!cursorInContent && (attributes & dragHasLeftSenderWindow))
  428.                 //if (!cursorInContent)
  429.                 {
  430.                     theRgn = NewRgn();
  431.                     RectRgn( theRgn, &theDoc->contentRect );
  432.                     ShowDragHilite( theDrag, theRgn, true );
  433.                     DisposeRgn( theRgn );
  434.                 }
  435.                 cursorInContent = true;
  436.             }
  437.             else
  438.             {
  439.                 if (cursorInContent && (attributes & dragHasLeftSenderWindow))
  440.                     HideDragHilite( theDrag );
  441.                 cursorInContent = false;
  442.             }
  443. //            }
  444.  
  445.             offset = HitTest( theMouse, theDoc );
  446.             break;
  447.  
  448.         case dragTrackingLeaveWindow:
  449.             //    Remove window highlighting, if showing.
  450.             if (cursorInContent && (attributes & dragHasLeftSenderWindow))
  451.                 HideDragHilite( theDrag );
  452.             break;
  453.  
  454.         case dragTrackingLeaveHandler:
  455.             break;
  456.  
  457.         default:
  458.             break;
  459.     }
  460.  
  461.     return noErr;
  462. }
  463.  
  464. pascal OSErr  Drag_DragSendDataProc(    FlavorType        theType,
  465.                                     void*            refCon,
  466.                                     ItemReference    theItem,
  467.                                     DragReference    theDrag)
  468. {
  469.  
  470.     DocPtr        theDoc = (DocPtr) refCon;
  471.     OSErr        err = noErr;
  472.     FSSpec        dropSpec;
  473.     unsigned    long    secs;
  474.     Str32        dateString;
  475.     Str32        untitledName;
  476.     Str32        tmpName;
  477.     Str32        indexStr;
  478.     FInfo        ignore ;
  479.     short        index = 1;
  480.     short        count;
  481.     ElemPtr        elem;
  482.     short        selectedElemCount, selectedFrameCount, i;
  483.     Boolean        singleFrame = false;
  484.     
  485.     // Set if only a single frame is selection
  486.     count = ElemColl_GetCount (theDoc->contentColl);
  487.     for (i=1; i <= count; i++)
  488.     {
  489.         elem = ElemColl_GetNthElem (theDoc->contentColl, i);
  490.         
  491.         if (Elem_GetSelected (elem))
  492.         {
  493.             ++selectedElemCount;
  494.             if (elem->elemType == kFrameElemType) ++selectedFrameCount;
  495.         }
  496.     }
  497.     
  498.     if ((selectedFrameCount == 1) && (selectedElemCount == 1)) singleFrame = true;
  499.  
  500.     switch (theType)
  501.     {
  502.     
  503.     
  504.         case kCAUserPromiseFlavor:
  505.         case kCABentoFlavor:
  506.  
  507.             if (singleFrame)
  508.             {
  509.                 // Let OpenDoc create the file
  510.                 err = badDragFlavorErr;
  511.                 break;
  512.             }
  513.             
  514.             // Create a CASample file from the selection
  515.             err = GetDropFSSpec(theDrag, &dropSpec);
  516.             
  517.             // Generate the file name:  "SourceFileName 1"
  518.             sCopyStr (theDoc->fileSpec.name, untitledName);
  519.             sAppendStr ("\p ", untitledName);
  520.  
  521.             // Generate unique name
  522.             //dropSpec.name[0] = 0;
  523.             //GetDateTime(&secs);
  524.             //IUDateString(secs,shortDate,(StringPtr)dateString);
  525.             //sCopyStr ("\puntitled ", untitledName);
  526.             //sAppendStr (dateString, untitledName);
  527.             //sAppendStr ("\p ", untitledName);
  528.             
  529.             do
  530.             {
  531.             
  532.                 sCopyStr (untitledName, tmpName);
  533.                 NumToString (index, (StringPtr) indexStr);
  534.                 sAppendStr (indexStr, tmpName);
  535.                 sCopyStr ((StringPtr) tmpName, dropSpec.name);
  536.                 ++index;
  537.  
  538.             } while (FSpGetFInfo( &dropSpec, &ignore ) == noErr);
  539.  
  540.             CAUtil_CreateDocFileFromSelection (theDoc, &dropSpec);
  541.             
  542.             err = SetDragItemFlavorData(theDrag, theItem, theType, &dropSpec, sizeof(FSSpec), 0L);
  543.  
  544.             err = noErr;
  545.             
  546.             break;
  547.             
  548.             
  549.         default:
  550.         
  551.             // The flavor may still be supplied internally, this
  552.             // just means that we don't 
  553.             err = badDragFlavorErr;
  554.             break;
  555.     
  556.     
  557.     }
  558.     
  559.     
  560.     return err;
  561.     
  562. }
  563.  
  564. //===========================================================================
  565. #pragma mark '    CASample Drag Routines
  566. //===========================================================================
  567.  
  568. //---------------------------------------------------------------------------
  569. //    Drag_DragItem 
  570.  
  571. Boolean Drag_DragItem(
  572.     WindowPtr        theWindow,
  573.     EventRecord        *theEvent )
  574. {
  575. OSErr                theErr;
  576. RgnHandle            dragRegion, tempRgn;
  577. PicHandle            thePicture;
  578. DocPtr                theDoc;
  579. Handle                theScrap;
  580. Point                saveOrigin;
  581. CADocumentRef        dragDropDoc;
  582. GrafPtr                savePort;
  583. CADropResult        dropResult;
  584. Handle                frameRefHandle;
  585. CASize                dataLength;
  586. PromiseHFSFlavor    thePromise;
  587. char                OSTypeStr[5];
  588. CAISOStr            typeStr;
  589. ElemListPtr            selectionList;
  590.  
  591.     if (!WaitMouseMoved( theEvent->where ))
  592.         return false;
  593.  
  594.     theDoc = (DocPtr)GetWRefCon( theWindow );
  595.  
  596.     // Get the ODDragDrop object
  597.     dragDropDoc = CAGetDragDropDocument(0);
  598.  
  599.     // Set the document kind to our internal scrap format
  600.     CASetDocumentKind(dragDropDoc, kCACASScrapTypeStr);
  601.  
  602.     // Create scrap data, including frame refs
  603.     theScrap = Doc_CreateCAScrapFromSelection( theDoc, dragDropDoc, kCACloneCut );
  604.         
  605.     if (!theScrap)
  606.     {
  607.         // Drag is a single embedded frame
  608.         
  609.         // that easy
  610.         
  611.     }
  612.     else
  613.     {
  614.  
  615.         // Write data to dragdrop
  616.         dataLength = GetHandleSize(theScrap);
  617.  
  618.         HLock( (Handle)theScrap );
  619.         CAWrite(dragDropDoc, (char*) *theScrap, &dataLength);
  620.         HUnlock( (Handle)theScrap );
  621.         
  622.         DisposHandle (theScrap);
  623.  
  624.         // Add kODHFSPromise for the finder, must support in dragsendproc
  625.  
  626.         /*
  627.         // Additional representations
  628.         
  629.         typeStr = CAISOStrFromOSType (kPICTType);
  630.         CASetDocumentKind(dragDropDoc, typeStr);
  631.         DisposePtr (typeStr);
  632.         
  633.         thePicture = Doc_CreateSelectionPicture( theDoc );
  634.     
  635.         dataLength = GetHandleSize((Handle)thePicture);
  636.         
  637.         HLock((Handle) thePicture);
  638.         CAWrite(dragDropDoc, (char*) thePicture, &dataLength);
  639.         HUnlock((Handle) thePicture);
  640.  
  641.         KillPicture(thePicture);*/
  642.         
  643.  
  644.     }
  645.  
  646.     // save the selection
  647.     selectionList = ElemColl_GetCurrentSelection (theDoc->contentColl);
  648.     
  649.     GetPort( &savePort );
  650.     SetPort( (GrafPtr)theWindow );
  651.  
  652.     // create the dragRegion in global coords
  653.     dragRegion = NewRgn();
  654.     Doc_CalcSelectionRgn(theDoc, dragRegion);
  655.  
  656.     GetOrigin( &saveOrigin );
  657.     Doc_SetGrafOrigin( theDoc );
  658.     RgnLocalToGlobal( dragRegion );
  659.  
  660.     SetOrigin( saveOrigin.h, saveOrigin.v );
  661.  
  662.     //    Prepare the drag region.
  663.     tempRgn = NewRgn();
  664.     CopyRgn( dragRegion, tempRgn );
  665.     InsetRgn( tempRgn, 1, 1 );
  666.     DiffRgn( dragRegion, tempRgn, dragRegion );
  667.     DisposeRgn( tempRgn );
  668.  
  669.     // Set the send data proc
  670.     CASetDataSendProc (dragDropDoc, gDragSendProcUPP, (void *) theDoc);
  671.  
  672.     localDragInProgress = true;
  673.     
  674.     //    Drag it
  675.     dropResult = CAStartDrag( theDoc->partDocRef, theEvent, dragRegion );
  676.  
  677.     localDragInProgress = false;
  678.  
  679.     if (dropResult == kCADropFail)
  680.         theErr = dragNotAcceptedErr;
  681.     else
  682.         theErr = noErr;
  683.         
  684.     DisposeRgn( dragRegion );
  685.  
  686.     CACloseDocument (dragDropDoc);
  687.  
  688.     if (dropResult == kCADropMove)
  689.     {
  690.         Doc_DeleteElements (theDoc, selectionList);
  691.         ElemList_Free (selectionList);
  692.     } 
  693.  
  694.  
  695.     // if it wasn't canceled by the user, then a drag occurred.
  696.     return (theErr == noErr);
  697.     
  698. }
  699.  
  700. //---------------------------------------------------------------------------
  701. Boolean Drag_DragItemHasFlavor(    DragReference    theDrag,
  702.                                     ItemReference    itemID,
  703.                                     OSType            theType)
  704. {
  705.     Boolean                result = false;
  706.     unsigned short        count;            
  707.     short                j;
  708.     OSType                itemType;
  709.  
  710.     CountDragItemFlavors(theDrag, itemID, &count);
  711.     for (j = 1; j <= count; j++)
  712.     {
  713.         OSErr err = GetFlavorType(theDrag, itemID, j, &itemType);
  714.         if ( err != noErr )
  715.             break;
  716.         if (itemType == theType)
  717.         {
  718.             result = true;
  719.             break;
  720.         }
  721.     }
  722.  
  723.     return result;
  724. }
  725.  
  726.  
  727. Handle Drag_GetFlavorData (    DragReference theDrag, 
  728.                             ItemReference theItem,
  729.                             OSType theType)
  730. {
  731.     Handle                dataHandle;
  732.     OSErr                theErr = noErr;
  733.     long                dataSize = 0;
  734.  
  735.     // get the flavor data size
  736.     theErr = GetFlavorDataSize( theDrag, theItem, theType, &dataSize );
  737.     if (theErr != noErr)
  738.     {
  739.         DEBUGSTR("\p Drag_GetFlavorData: error after GetFlavorDataSize");
  740.         return NULL;
  741.     }
  742.  
  743.     // allocate the space
  744.     dataHandle = NewHandle( dataSize );
  745.     if (dataHandle == nil)
  746.     {
  747.         DEBUGSTR( "\p Drag_GetFlavorData: NewHandle failed" );
  748.         return NULL;
  749.     }
  750.  
  751.     // Get the actual flavor data.
  752.     HLock( dataHandle);
  753.     theErr = GetFlavorData(theDrag, theItem, theType, *dataHandle, &dataSize, 0L );
  754.     HUnlock( dataHandle );
  755.             
  756.     if (theErr != noErr)
  757.     {
  758.         DEBUGSTR( "\p MyReceiveDropHandler: error after GetFlavorData" );
  759.         DisposeHandle( dataHandle );
  760.         return NULL;
  761.     }
  762.     
  763.     return (dataHandle);
  764.  
  765. }
  766.  
  767.  
  768. //---------------------------------------------------------------------------
  769. //    Returns true if the given dropLocation AEDesc is a descriptor of the Finder's Trash.
  770.  
  771. static Boolean DropLocationIsFinderTrash(
  772.     AEDesc    *dropLocation )
  773. {
  774. OSErr            theErr;
  775. AEDesc            dropSpec;
  776. FSSpec            *theSpec;
  777. CInfoPBRec        thePB;
  778. short            trashVRefNum;
  779. long            trashDirID;
  780.  
  781.     //    Coerce the dropLocation descriptor to an FSSpec. If there's no dropLocation or
  782.     //    it can't be coerced into an FSSpec, then it couldn't have been the Trash.
  783.     theErr = AECoerceDesc( dropLocation, typeFSS, &dropSpec );
  784.     if ((dropLocation->descriptorType != typeNull) && (theErr == noErr))
  785.     {
  786.         HLock( dropSpec.dataHandle );
  787.         theSpec = (FSSpec*)*dropSpec.dataHandle;
  788.  
  789.         /* Get the directory ID of the given dropLocation object. */
  790.         thePB.dirInfo.ioCompletion = 0L;
  791.         thePB.dirInfo.ioNamePtr = (StringPtr) &theSpec->name;
  792.         thePB.dirInfo.ioVRefNum = theSpec->vRefNum;
  793.         thePB.dirInfo.ioFDirIndex = 0;
  794.         thePB.dirInfo.ioDrDirID = theSpec->parID;
  795.  
  796.         theErr = PBGetCatInfo( &thePB, false );
  797.  
  798.         HUnlock(dropSpec.dataHandle);
  799.         AEDisposeDesc(&dropSpec);
  800.  
  801.         if (theErr != noErr)
  802.             return false;
  803.  
  804.         //    If the result is not a directory, it must not be the Trash.
  805.         if (!(thePB.dirInfo.ioFlAttrib & (1 << 4)))
  806.             return false;
  807.  
  808.         //    Get information about the Trash folder.
  809.         theErr = FindFolder(
  810.             theSpec->vRefNum, kTrashFolderType, kCreateFolder,
  811.             &trashVRefNum, &trashDirID );
  812.         if (theErr != noErr)
  813.             return false;
  814.  
  815.         //    If the directory ID of the dropLocation object is the same as the directory ID
  816.         //    returned by FindFolder, then the drop must have occurred into the Trash.
  817.         if (thePB.dirInfo.ioDrDirID == trashDirID)
  818.             return true;
  819.     }
  820.  
  821.     return false;
  822. }
  823.  
  824. //---------------------------------------------------------------------------
  825. //    Given a point in global coordinates, HitTest returns 1 if the point is inside
  826. //    the content area of the window. If the point is not inside the window, 
  827. //    HitTest return 0. Note: this should return the insertion item number. if
  828. //     the Scrapbook were modified to show more than one item at a time.
  829.  
  830. static short HitTest(
  831.     Point    theLoc,
  832.     DocPtr    theDoc )
  833. {
  834. #if 1
  835. Point    localMouse;
  836.  
  837.     localMouse = theLoc;
  838.     GlobalToLocal( &localMouse );
  839.  
  840.     if (PtInRect( localMouse, &theDoc->contentRect ))
  841.         return 1;
  842.     else
  843.         return 0;
  844. #else
  845.     return 1;
  846. #endif
  847. }
  848.  
  849. #if 0
  850. //---------------------------------------------------------------------------
  851. // given a fileSpec, get the first resource of theType from the resource file and 
  852. // return it in the handle after detaching if from the resource file.
  853.  
  854. static OSErr GetResFromFile(
  855.     FSSpec    *fileSpec,
  856.     Handle    *h,
  857.     OSType    theType )
  858. {
  859. OSErr        theErr;
  860. short        theFileNum, savedResFile;
  861. short        theCount;
  862.  
  863.     *h = nil;
  864.     theErr = noErr;
  865.     savedResFile = CurResFile();
  866.  
  867.     theFileNum = FSpOpenResFile( fileSpec, fsRdPerm );
  868.     theErr = ResError();
  869.     if (theErr != noErr)
  870.         goto closeout;
  871.  
  872.     theCount = Count1Resources( theType );
  873.     if (theCount < 1)
  874.     {
  875.         theErr = resNotFound;
  876.         goto closeout;
  877.     }
  878.  
  879.     *h = Get1IndResource( theType, 1 );    // get the first resource of theType
  880.     DetachResource( *h );
  881.  
  882. closeout:
  883.     if (theFileNum > 0)
  884.         CloseResFile( theFileNum );
  885.     if (savedResFile >= 0)
  886.         UseResFile( savedResFile );
  887.  
  888.     return theErr;
  889. }
  890. #endif
  891.  
  892. //---------------------------------------------------------------------------
  893. // given a fileSpec, return the date from the data fork of the file starting
  894. // at offset and continuing to maxLength or the end of the file.
  895.  
  896. static OSErr GetDataFromFile(
  897.     FSSpec    *fileSpec,
  898.     Handle    *h,
  899.     long    offset,
  900.     long    maxLength )
  901. {
  902. OSErr        theErr;
  903. long        fileLength;
  904. short        theFileNum;
  905.  
  906.     *h = nil;
  907.     theErr = noErr;
  908.     theFileNum = 0;
  909.  
  910.     theErr = FSpOpenDF( fileSpec, fsRdPerm, &theFileNum );
  911.     if (theErr != noErr)
  912.         goto closeout;
  913.  
  914.     theErr = GetEOF( theFileNum, &fileLength );
  915.     if (theErr != noErr)
  916.         goto closeout;
  917.  
  918.     if (fileLength < offset)
  919.     {
  920.         theErr = eofErr;
  921.         goto closeout;
  922.     }
  923.  
  924.     fileLength -= offset;
  925.     if (fileLength > maxLength)
  926.         fileLength = maxLength;
  927.  
  928.     *h = NewHandle (fileLength);
  929.     theErr = MemError();
  930.     if (theErr != noErr)
  931.         goto closeout;
  932.  
  933.     theErr = SetFPos( theFileNum, fsFromStart, offset );        // skip any header
  934.     if (theErr != noErr)
  935.         goto closeout;
  936.  
  937.     theErr = FSRead( theFileNum, &fileLength, **h );
  938.  
  939. closeout:
  940.     if (theFileNum > 0)
  941.         FSClose( theFileNum );
  942.  
  943.     return theErr;
  944. }
  945.  
  946. //---------------------------------------------------------------------------
  947. // loop through all the drag items and make sure there is at least one flavor
  948. // (in each item) that we can accept.
  949.  
  950. static Boolean IsMyTypeAvailable(
  951.     DragReference    theDrag )
  952. {
  953. OSErr                theErr;
  954. unsigned short        numItems, index;
  955.  
  956.  
  957.     theErr = CountDragItems( theDrag, &numItems );
  958.     if ((theErr != noErr) || (numItems <= 0))
  959.         return false;
  960.  
  961.     //    Loop through all of the drag items contained in this drag.
  962.     for (index = 1; index <= numItems; index++)
  963.     {
  964.         ItemReference        theItem;
  965.         unsigned short        flavorIndex;
  966.         FlavorType            theType;
  967.         Size                dataSize;
  968.         FlavorFlags            theFlags;
  969.         HFSFlavor            theHFSFlavor;
  970.  
  971.         //    Get the item's reference number, so we can refer to it.
  972.         theErr = GetDragItemReferenceNumber( theDrag, index, &theItem );
  973.         if (theErr)
  974.             break;
  975.             
  976.         if (Drag_DragItemHasFlavor (theDrag, theItem, kCAPromiseFlavor))
  977.         {
  978.             // Can always embed the drag contents
  979.             return true;
  980.         }
  981.         else if (Drag_DragItemHasFlavor (theDrag, theItem, kCACASScrapType))
  982.         {
  983.             return true;
  984.         }
  985.         else if (Drag_DragItemHasFlavor (theDrag, theItem, flavorTypeHFS))
  986.         {
  987.             dataSize = sizeof(theHFSFlavor);
  988.             theErr = GetFlavorData( theDrag, theItem, flavorTypeHFS, &theHFSFlavor, &dataSize, 0L );
  989.             if (theErr != noErr)
  990.             {
  991.                 DEBUGSTR( "\p IsMyTypeAvailable: error after GetFlavorData" );
  992.                 continue;    // go on to the next flavor.
  993.             }
  994.  
  995.             // if it's a Finder clipping…
  996.             if (theHFSFlavor.fileCreator == 'drag')
  997.                 continue;    // go on to the next flavor. There should be another flavor we like.
  998.  
  999.             // if it's a PICT, we'll take it.
  1000.             if (theHFSFlavor.fileType == kPICTType)
  1001.                 return true;
  1002.                     
  1003.             if (theHFSFlavor.fileCreator == kODShellSignature)
  1004.                 return true;
  1005.  
  1006.             if (theHFSFlavor.fileCreator == kOurFileCreator)
  1007.                 return true;
  1008.  
  1009.         }
  1010.  
  1011.     }
  1012.  
  1013.     return false;        // didn't find any suitable flavors.
  1014. }
  1015.  
  1016. //---------------------------------------------------------------------------
  1017. static OSErr GetDropFSSpec(DragReference theDrag, FSSpec *dropFSSpec)
  1018. {
  1019.     AEDesc            dropDescriptor;
  1020.     CInfoPBRec        getInfoPB;
  1021.  
  1022.     OSErr result = GetDropLocation(theDrag, &dropDescriptor);
  1023.     if (result != noErr || dropDescriptor.descriptorType == typeNull)
  1024.         result = fnfErr;            // Can't create a file unless we know where it goes!
  1025.     else
  1026.     {
  1027.         AEDesc fssDescriptor;
  1028.         result = AECoerceDesc(&dropDescriptor, typeFSS, &fssDescriptor);
  1029.         AEDisposeDesc(&dropDescriptor);
  1030.         if (result == noErr) {        
  1031.             BlockMove(*fssDescriptor.dataHandle, dropFSSpec, sizeof(FSSpec));
  1032.             AEDisposeDesc(&fssDescriptor);
  1033.  
  1034.             // Use PBGetCatInfo to get the directoryID of the target directory.
  1035.             getInfoPB.dirInfo.ioCompletion = 0L;
  1036.             getInfoPB.dirInfo.ioNamePtr = (StringPtr) &(dropFSSpec->name);
  1037.             getInfoPB.dirInfo.ioVRefNum = dropFSSpec->vRefNum;
  1038.             getInfoPB.dirInfo.ioFDirIndex = 0;
  1039.             getInfoPB.dirInfo.ioDrDirID = dropFSSpec->parID;
  1040.             result = PBGetCatInfo(&getInfoPB, false);
  1041.             if (result == noErr)
  1042.             {
  1043.                 dropFSSpec->parID = getInfoPB.dirInfo.ioDrDirID;
  1044.                 dropFSSpec->name[0] = 0;
  1045.             }
  1046.         }
  1047.     }
  1048.     
  1049.     return result;
  1050. }
  1051.  
  1052. //===========================================================================
  1053. #pragma mark '    Pre-CAList Drag Methods
  1054. //===========================================================================
  1055.  
  1056.  
  1057. #ifdef USE_CALIB
  1058. //---------------------------------------------------------------------------
  1059. //
  1060. //    DragItem - Drag the selected items from the window. Return true if a 
  1061. //     drag occurs or false if not.
  1062.  
  1063. Boolean DragItem(
  1064.     WindowPtr        theWindow,
  1065.     EventRecord        *theEvent )
  1066. {
  1067. #ifdef OLDWAY
  1068. OSErr                theErr;
  1069. RgnHandle            dragRegion, tempRgn;
  1070. DragReference        theDrag;
  1071. AEDesc                dropLocation;
  1072. DragAttributes        attributes;
  1073. short                mouseDownModifiers,
  1074.                     mouseUpModifiers,
  1075.                     copyItem;
  1076. PicHandle            thePicture;
  1077. DocPtr                theDoc;
  1078. Handle                theScrap;
  1079. Point                saveOrigin;
  1080. CADocumentRef        dragDropDoc;
  1081. ItemReference        item = 1;
  1082. GrafPtr                savePort;
  1083. CADropResult        dropResult;
  1084.  
  1085.     //    Wait for the mouse to move or the mouse button to be released. If the mouse button was
  1086.     //    released before the mouse moves, return false. Returning false from DragItem means that
  1087.     //    a drag operation did not occur.
  1088.     if (!WaitMouseMoved( theEvent->where ))
  1089.         return false;    // indicate that a drag did not occur.
  1090.  
  1091.     theDoc = (DocPtr)GetWRefCon( theWindow );
  1092.  
  1093.     // create the drag ($$$$$ ignore any errors?).
  1094.     NewDrag( &theDrag );
  1095.  
  1096. #ifdef USE_CALIB
  1097. {
  1098.     Handle            frameRefHandle;
  1099.     
  1100.     // Get the ODDragDrop object
  1101.  
  1102.     dragDropDoc = CAGetDragDropDocument(&item, kCACloneCopy);
  1103.     CASetDocumentKind(dragDropDoc, kCACASScrapTypeStr);
  1104.     
  1105.     // Clone frames
  1106.     //frameRefHandle = Doc_CloneSelectedFrames (theDoc, dragDropDoc);
  1107.  
  1108.     // Copy our own format "kCACASScrapType" data to the scrap
  1109.     theScrap = Doc_CreateCAScrapFromSelection( theDoc, dragDropDoc, kCACloneCut );
  1110.     
  1111.     DisposHandle (frameRefHandle);
  1112.     
  1113.     // Call CACloseDocument after the drag is complete
  1114.  
  1115. }
  1116. #else
  1117.  
  1118.     // Add our own format first
  1119.     theScrap = Doc_CreateScrapFromSelection(theDoc);
  1120.     
  1121. #endif
  1122.  
  1123.     if (theScrap)
  1124.     {
  1125.  
  1126.         HLock( (Handle)theScrap );
  1127.  
  1128. #ifdef USE_CALIB
  1129.  
  1130.         AddDragItemFlavor(
  1131.             theDrag, item, kCACASScrapType, (Ptr) *theScrap,
  1132.             GetHandleSize( (Handle)theScrap ), 0 );
  1133.  
  1134. #else
  1135.  
  1136.         AddDragItemFlavor(
  1137.             theDrag, 1, kCASScrapType, (Ptr) *theScrap,
  1138.             GetHandleSize( (Handle)theScrap ), 0 );
  1139.             
  1140. #endif
  1141.         HUnlock( (Handle)theScrap );
  1142.  
  1143.         // get rid of the picture.
  1144.         DisposHandle (theScrap);
  1145.     }
  1146. #ifdef USE_CALIB
  1147.  
  1148.     else
  1149.     {
  1150.     
  1151.         // Single embedded frame
  1152.         
  1153.         //AddDragItemFlavor(
  1154.         //    theDrag, 1, kODBentoFlavor, 0, 0, 0 );
  1155.             
  1156.         AddDragItemFlavor(
  1157.             theDrag, item, kCABentoFlavor,  0, 0, 0 );
  1158.  
  1159.     }
  1160.     
  1161. #endif
  1162.     
  1163.     
  1164.     /*
  1165.     // create a picture from the selected items.
  1166.     thePicture = Doc_CreateSelectionPicture( theDoc );
  1167.     if (thePicture == nil)
  1168.         return(false);
  1169.  
  1170.     // add our picture to the drag ($$$$$ ignore any errors?).
  1171.     HLock((Handle) thePicture);
  1172.     AddDragItemFlavor(
  1173.         theDrag, item, kPICTType, (Ptr)*thePicture,
  1174.         GetHandleSize( (Handle)thePicture), 0 );
  1175.     HUnlock((Handle) thePicture);
  1176.  
  1177.     // get rid of the picture.
  1178.     KillPicture(thePicture);*/
  1179.  
  1180.     GetPort( &savePort );
  1181.     SetPort( (GrafPtr)theWindow );
  1182.  
  1183.     
  1184.     // create the dragRegion from the selection and offset it into global coordinates.
  1185.     dragRegion = NewRgn();
  1186.     Doc_CalcSelectionRgn(theDoc, dragRegion);
  1187.  
  1188.     GetOrigin( &saveOrigin );
  1189.     Doc_SetGrafOrigin( theDoc );
  1190.  
  1191.     RgnLocalToGlobal( dragRegion );
  1192.  
  1193.     SetOrigin( saveOrigin.h, saveOrigin.v );
  1194.  
  1195.     //    Set the item's bounding rectangle in global coordinates.
  1196.     //SetDragItemBounds( theDrag, item, &(**dragRegion).rgnBBox );
  1197.  
  1198.     //    Prepare the drag region.
  1199.     tempRgn = NewRgn();
  1200.     CopyRgn (dragRegion, tempRgn );
  1201.     InsetRgn (tempRgn, 1, 1 );
  1202.     DiffRgn (dragRegion, tempRgn, dragRegion );
  1203.     DisposeRgn (tempRgn);
  1204.     
  1205.     SetPort(savePort);
  1206.  
  1207.     CASetDataSendProc (theDrag, gDragSendProcUPP, (void *) NULL);
  1208.  
  1209.     //    Drag the item. TrackDrag will return userCanceledErr if the drop zoomed-back
  1210.     //    for any reason.
  1211.     //theErr = TrackDrag( theDrag, theEvent, dragRegion );
  1212.     dropResult = CAStartDrag( theDoc->partDocRef, theDrag, theEvent, dragRegion );
  1213.  
  1214.     theErr = noErr;
  1215.     
  1216.     //    Dispose of the drag.
  1217.     DisposeDrag( theDrag );
  1218.     DisposeRgn( dragRegion );
  1219.  
  1220. #ifdef USE_CALIB
  1221.     CACloseDocument (dragDropDoc);
  1222. #endif
  1223.  
  1224.     if (dropResult == kCADropMove)
  1225.     {
  1226.         //Doc_DeleteSelection (theDoc);
  1227.     } 
  1228.     
  1229.  
  1230.     if ((theErr != noErr) && (theErr != userCanceledErr))    // if an error occured
  1231.         return false;    // indicate that a drag did not occur.
  1232.  
  1233.     //    Check to see if the drop occurred in the Finder's Trash. If the drop occurred
  1234.     //    in the Finder's Trash and a copy operation wasn't specified, delete the
  1235.     //    source selection. Note that we can continue to get the attributes, drop location
  1236.     //    modifiers, etc. of the drag until we dispose of it using DisposeDrag.
  1237.  
  1238.  
  1239. #if 0    // The DropLocationIsFinderTrash call causes a crash on AECoerceDesc
  1240.     GetDragAttributes( theDrag, &attributes );
  1241.     if (!(attributes & dragInsideSenderApplication))
  1242.     {
  1243.         GetDropLocation( theDrag, &dropLocation );
  1244.  
  1245.         GetDragModifiers( theDrag, 0L, &mouseDownModifiers, &mouseUpModifiers );
  1246.         copyItem = (mouseDownModifiers | mouseUpModifiers) & optionKey;
  1247.  
  1248.         if (!copyItem && DropLocationIsFinderTrash(&dropLocation) && !theDoc->fileLocked)
  1249.             Doc_ClearMenu( theDoc );
  1250.  
  1251.         AEDisposeDesc( &dropLocation );
  1252.     }
  1253. #endif
  1254.  
  1255.     // if it wasn't canceled by the user, then a drag occurred.
  1256.     return (theErr != userCanceledErr);
  1257.     
  1258. #endif
  1259. }
  1260.  
  1261.  
  1262. #endif
  1263.  
  1264.  
  1265.  
  1266.  
  1267.  
  1268. #ifndef USE_CALIB
  1269. //---------------------------------------------------------------------------
  1270. //
  1271. //    Drag_DragReceiveHandler - Called by the Drag Manager when a drop occurs over our window.
  1272.  
  1273. pascal OSErr Drag_DragReceiveHandler(
  1274.     WindowPtr        theWindow,
  1275.     void            *handlerRefCon,
  1276.     DragReference    theDrag )
  1277. {
  1278. OSErr                theErr;
  1279. unsigned short        numItems, index;
  1280. DragAttributes        attributes;
  1281. short                mouseDownModifiers, mouseUpModifiers;
  1282. GrafPtr                savePort;
  1283. DocPtr                theDoc;
  1284. Boolean                skipPict = false;
  1285.  
  1286.     // if we can't accept the item flavors or the cursor isn't over the item frame,
  1287.     // don't accept the drag.
  1288.     if (!canAcceptItems || !cursorInContent)
  1289.         return dragNotAcceptedErr;
  1290.  
  1291.     theDoc = (DocPtr)GetWRefCon( theWindow );
  1292.  
  1293.     GetPort( &savePort );
  1294.     SetPort( (GrafPtr)theWindow );
  1295.  
  1296.     theErr = GetDragAttributes( theDrag, &attributes );
  1297.  
  1298.     // are we moving the items within our own window?
  1299.     if (attributes & dragInsideSenderWindow)
  1300.     {
  1301.         Point    startPt, endPt;
  1302.  
  1303.         // This is where we move the items.
  1304.         theErr = GetDragOrigin( theDrag, &startPt );
  1305.         theErr = GetDragMouse( theDrag, &endPt, nil );
  1306.  
  1307.         Doc_MoveSelection( theDoc, endPt.h - startPt.h, endPt.v - startPt.v );
  1308.  
  1309.         SetPort( savePort );
  1310.         return noErr;
  1311.     }
  1312.  
  1313.     theErr = GetDragModifiers( theDrag, 0L, &mouseDownModifiers, &mouseUpModifiers );
  1314.     if (theErr != noErr)
  1315.     {
  1316.         SetPort( savePort );
  1317.         return theErr;
  1318.     }
  1319.  
  1320.     theErr = CountDragItems( theDrag, &numItems );
  1321.     if (theErr != noErr)
  1322.     {
  1323.         SetPort( savePort );
  1324.         return theErr;
  1325.     }
  1326.  
  1327.     if (numItems <= 0)            // if there is nothing to receive…
  1328.     {
  1329.         SetPort( savePort );
  1330.         theErr = dragNotAcceptedErr;
  1331.         return theErr;
  1332.     }
  1333.  
  1334.     // turn off the hiliting if needed
  1335.     if (attributes & dragHasLeftSenderWindow)
  1336.         HideDragHilite( theDrag );
  1337.  
  1338. //    page = GetCtlValue(theDoc->scrollBar);                            /* get current page */
  1339.  
  1340.     //    Loop through all of the drag items contained in this drag and add an item for each.
  1341.     for (index = 1; index <= numItems; index++)
  1342.     {
  1343.     ItemReference        theItem;
  1344.     unsigned short        numFlavors;
  1345.     unsigned short        flavorIndex;
  1346.     FlavorType            theType;
  1347.     Size                dataSize;
  1348.     FlavorFlags            theFlags;
  1349.  
  1350. DebugStr ("\pd2");
  1351.  
  1352.         //    Get the item's reference number, so we can refer to it.
  1353.         // count the number of item flavors.
  1354.         theErr = GetDragItemReferenceNumber( theDrag, index, &theItem );
  1355.         theErr = CountDragItemFlavors( theDrag, theItem, &numFlavors );
  1356.  
  1357.         // loop through all the drag item flavors and add them to the new item.
  1358.         for (flavorIndex = 1; flavorIndex <= numFlavors; flavorIndex++)
  1359.         {
  1360.         Handle        h;
  1361.  
  1362.             // get the flavor type
  1363.             theErr = GetFlavorType( theDrag, theItem, flavorIndex, &theType );
  1364.             if (theErr != noErr)
  1365.             {
  1366.                 DEBUGSTR( "\p MyReceiveDropHandler: error after GetFlavorType" );
  1367.                 continue;
  1368.             }
  1369.  
  1370.             if ((theType == flavorTypePromiseHFS)    // ignore old Sys 7 Pro Finder 'phfs' promised flavor. Tip from PixelPaint dudes.
  1371.                 || (theType == flavorTypeDirectory)    // ignore OCE types 'diry'. Tip from Eric Hanig at Oracle.
  1372.                 || (theType == 'movr'))                // ignore Finder movr flavor since it's empty
  1373.                 continue;
  1374.  
  1375.             // Get the flavor flags
  1376.             theErr = GetFlavorFlags( theDrag, theItem, theType, &theFlags );
  1377.             if (theErr != noErr)
  1378.             {
  1379.                 DEBUGSTR("\p MyReceiveDropHandler: error after GetFlavorFlags");
  1380.                 continue;
  1381.             }
  1382.  
  1383.             if ((theFlags & flavorSystemTranslated)        // don't take any translation manager flavors.
  1384.                 || (theFlags & flavorNotSaved)            // don't take any flavors that will become stale.
  1385.                 || (theFlags & flavorSenderOnly))        // don't take any flavors that are for the sender only
  1386.                 continue;
  1387.  
  1388.             // get the flavor data size
  1389.             theErr = GetFlavorDataSize( theDrag, theItem, theType, &dataSize );
  1390.             if (theErr != noErr)
  1391.             {
  1392.                 DEBUGSTR("\p MyReceiveDropHandler: error after GetFlavorDataSize");
  1393.                 continue;
  1394.             }
  1395.  
  1396.             // if it's got no data, skip it.
  1397.             if (dataSize <= 0L)
  1398.                 continue;
  1399.  
  1400.             // allocate the space
  1401.             h = NewHandle( dataSize );
  1402.             if (h == nil)
  1403.             {
  1404.                 DEBUGSTR( "\p MyReceiveDropHandler: NewHandle failed" );
  1405.                 continue;
  1406.             }
  1407.  
  1408.             // Get the actual flavor data.
  1409.             HLock( h);
  1410.             theErr = GetFlavorData(theDrag, theItem, theType, *h, &dataSize, 0L );
  1411.             HUnlock( h );
  1412.             if (theErr != noErr)
  1413.             {
  1414.                 DEBUGSTR( "\p MyReceiveDropHandler: error after GetFlavorData" );
  1415.                 DisposeHandle( h );                                            /* clean up */
  1416.                 continue;
  1417.             }
  1418. DebugStr ("\pd3");
  1419.  
  1420.             if (theType == kCACASScrapType)
  1421.             {
  1422.             Point            dropPoint;
  1423.             Rect            itemBounds;
  1424.             Rect            docBounds;
  1425.             GrafPtr            savePort;
  1426.             CADocumentRef    dragDropDoc;
  1427.  
  1428.                 GetPort( &savePort );
  1429.                 SetPort( (GrafPtr)Doc_GetWindow( theDoc ) );
  1430.  
  1431.                 // Calc our docs window rect in global coords.
  1432.                 docBounds = theWindow->portRect;
  1433.  
  1434.                 GetDragItemBounds( theDrag, theItem, &itemBounds );
  1435.  
  1436.                 dropPoint.v = itemBounds.top - docBounds.top;
  1437.                 dropPoint.h = itemBounds.left - docBounds.left;
  1438.  
  1439.                 GlobalToLocal( &dropPoint );
  1440.  
  1441.                 SetPort( savePort );
  1442.  
  1443.         
  1444.                 dragDropDoc = CAGetDragDropDocument(kCACloneDropCopy);
  1445.                 Doc_AddItemsFromCAScrap( theDoc, h, &dropPoint, dragDropDoc );
  1446.  
  1447.                 //Doc_AddItemsFromScrap (theDoc, h, dropPoint);
  1448.                 DisposeHandle( h );
  1449.                 skipPict = true;
  1450.                 continue;
  1451.             }
  1452.  
  1453.             // if it's a file/folder (hfs ) from the Finder check it's type
  1454.             // and see if we can read it into a handle
  1455.             else if (theType == flavorTypeHFS)
  1456.             {
  1457.             HFSFlavor        theHFSFlavor;
  1458.  
  1459.                 // save the flavor
  1460.                 BlockMoveData( *h, &theHFSFlavor, (long)sizeof(HFSFlavor) );
  1461.  
  1462.                 DisposeHandle( h );    // throw away the handle, we'll get a new one.
  1463.                 h = nil;
  1464.  
  1465.                 if (theHFSFlavor.fileType == kPICTType)                // PICT file?
  1466.                 {
  1467.                     theType = kPICTType;
  1468.  
  1469.                     // open the data fork and read the pict out of it.
  1470.                     theErr = GetDataFromFile(&theHFSFlavor.fileSpec, &h, 512, 0x7FFFFFFF);
  1471.                 }
  1472.                 else if (theHFSFlavor.fileCreator == 'drag')    // CREATOR is Finder clipping file?
  1473.                 {
  1474.                     // ignore it since we'll get the clipping flavors also.
  1475.                     theErr = noErr;
  1476.                     continue;
  1477.                 }
  1478.                 else
  1479.                 {
  1480.                     // indicate we don't have anything.
  1481.                     theErr = resNotFound;
  1482.                 }
  1483.             }
  1484.  
  1485.             else if ((theType == kPICTType) && skipPict)
  1486.             {
  1487.                 DisposeHandle( h );
  1488.                 continue;
  1489.             }
  1490.             // $$$$$ add the PICT (h) to our list at the correct point.
  1491.             if (theErr == noErr)
  1492.             {
  1493.             Point        dropPoint;
  1494.             Rect        itemBounds;
  1495.             Rect        docBounds;
  1496.  
  1497.                 // Calc our docs window rect in global coords.
  1498.                 docBounds.top = theWindow->portRect.top;
  1499.                 docBounds.left = theWindow->portRect.left;
  1500.                 docBounds.bottom = theWindow->portRect.bottom;
  1501.                 docBounds.right = theWindow->portRect.right;
  1502.  
  1503.                 GetDragItemBounds (theDrag, theItem, &itemBounds);
  1504.  
  1505.                 dropPoint.v = itemBounds.top - docBounds.top;
  1506.                 dropPoint.h = itemBounds.left - docBounds.left;
  1507.  
  1508.                 Doc_AddItemPict( theDoc, (PicHandle)h, dropPoint );
  1509.                 DisposeHandle( h );     // h was allocated in GetDataFromFile
  1510. //                AddResource(h, theType, resID, "\p");
  1511. //                theErr = ResError();
  1512.             }
  1513.         }
  1514.     }
  1515. DebugStr ("\pd4");
  1516.  
  1517.     Doc_SetDirty(theDoc, true);         // mark it changed
  1518.  
  1519.     // $$$$$ if nothing was dropped, return an error (dragNotAcceptedErr)
  1520.     return noErr;
  1521. }
  1522. #endif